<script setup lang="ts">
import type { IMatchConfig, IMatchingGroup, IMatchingRule } from './types'

import { cloneDeep } from 'lodash-es'

import { v4 as uuidV4 } from 'uuid'
import { filterFromArray } from '@/utils/cdn'
import MatchingGroup from './components/MatchingGroup.vue'
import { getMatchConfig } from './config'
import {
  formatMatchingRules,
  getFieldConfig,
  getFieldValue,
  getOperatorTemplate,
  getSecondAllowValue,
  handleRuleValue,
} from './utils'

type ConfigureFn = (arr: IMatchConfig[]) => IMatchConfig[]
interface IEmit {
  (event: 'update:modelValue', value: IMatchingGroup[]): void
}

interface IProps {
  disabledAll?: boolean
  modelValue: IMatchingGroup[]
  includes?: string[]
  excludes?: string[]
  // secondExcludes?: string[]
  // 匹配规则配置函数，会传入系统内置的所有规则配置，外部调用者可对系统配置进行覆盖重置
  configure?: ConfigureFn | ConfigureFn[]
}

const props = defineProps<IProps>()
const emit = defineEmits<IEmit>()
const groupRefs = ref<(typeof MatchingGroup)[]>([])
const matchingGroups = useVModel(props, 'modelValue', emit)
provide('groups', matchingGroups)

/** 是否允许自定义参数 */
const hasCustom = computed(() => {
  return matchingGroups.value[0].rules.some((item) => {
    const config = getFieldConfig(item.field)
    if (!config?.needCustomField)
      return false
    return true
  })
})
/**
  value_count为0时，不显示值
 */
const showValueColumn = computed(() => {
  if (
    matchingGroups.value[0].rules.length === 1
    && getFieldValue(matchingGroups.value[0].rules[0])?.count === 0
  ) {
    return false
  }
  return true
})
/**
 * 组规则改变
 */
function handleGroupRuleChange(uuid: string, rules: IMatchingRule[]) {
  const group = matchingGroups.value.find(item => item.uuid === uuid)
  if (group) {
    group.rules = rules
  }
}

/**
 * 新增组（或者）
 */
// function handleAddGroup() {
//   matchingGroups.value.push({
//     uuid: uuidV4(),
//     rules: [{ uuid: uuidV4(), field: '', operator: '', value: '' }]
//   })
//   console.log('matchingGroups.value: ', matchingGroups.value)
// }

/**
 * 生成规则模板数据，外部调用
 */
function generateTemplate() {
  const ruleList: string[] = []
  matchingGroups.value.forEach((group) => {
    const groupRules: string[] = []
    group.rules.forEach((item) => {
      const config = getFieldConfig(item.field)
      if (!config || !item.operator) {
        return
      }
      const operatorTemplate = getOperatorTemplate(
        config.operatorOptions,
        item.operator,
      )
      const value = handleRuleValue(item.operator, item.value)
      if (config.field.valueType === 'boolean') {
        groupRules.push(`${item.value === 2 ? 'not ' : ''}${item.field}`)
      } else {
        groupRules.push(
          operatorTemplate
            .replace('$field', item.field)
            .replace('$value', value),
        )
      }
    })
    ruleList.push(groupRules.join(' and '))
  })
  let template: string = ''
  if (ruleList.length === 1) {
    template = `(${ruleList[0]})`
  } else {
    template = ruleList
      .map((item) => {
        return `(${item})`
      })
      .join(' or ')
  }
  return template
}

/**
 * 重置
 */
function reset() {
  matchingGroups.value = [
    {
      uuid: uuidV4(),
      rules: [
        { uuid: uuidV4(), field: '', operator: '', value: '', custom_field: '' },
      ],
    },
  ]
}

// 验证数据
async function validate() {
  const res = await Promise.all(
    groupRefs.value.map(groupComp => groupComp.validate()),
  )
  return res.map((res: any) => res.every((item: any) => item === undefined))[0]
}

const sliceMatchConfig = computed(() => {
  let configs: IMatchConfig[] = cloneDeep(getMatchConfig())
  if (props.includes) {
    configs = filterFromArray(configs, props.includes, 'value')
  }
  if (props.excludes) {
    configs = filterFromArray(configs, props.excludes, 'value', 'excludes')
  }
  // if (props.secondExcludes) {
  //   configs = excludeFromSecondArray(configs, props.secondExcludes, 'value')
  // }
  if (props.configure) {
    if (Array.isArray(props.configure)) {
      props.configure.forEach((fn) => {
        configs = fn(configs)
      })
    } else {
      configs = props.configure(configs)
    }
  }
  return configs
})
provide('matchConfig', sliceMatchConfig)
const tableData = ref<{ field: string, operator: string, value: string }[]>([])
watchEffect(() => {
  formatMatchingRules(props.modelValue[0]?.rules ?? []).then((res) => {
    tableData.value = res
  })
})

// const columns = computed(() => buildColumns([
//   {
//     title: '匹配字段',
//     dataIndex: 'field',
//     render: ({ record }) => record.field,
//   },
//   {
//     title: '运算符',
//     dataIndex: 'operator',
//     render: ({ record }) => record.operator,
//   },
//   {
//     title: '值',
//     dataIndex: 'value',
//     render({ record }) {
//       if (Array.isArray(record.value)) {
//         return record.value.join(',')
//       }
//       const allowed_values = getSecondAllowValue(
//         record,
//         'origin_field',
//         record.origin_operator,
//       )
//       if (allowed_values?.length) {
//         return getOptionsLabel(allowed_values, record.value)
//       }
//       return record.value
//     },
//   },
// ]))

const columns = buildColumns([
  {
    title: '匹配字段',
    dataIndex: 'field',
    render: ({ record }) => record.field,
  },
  {
    title: '运算符',
    dataIndex: 'operator',
    render: ({ record }) => record.operator,
  },
  {
    title: '值',
    dataIndex: 'value',
    slotName: 'value',
    render({ record }) {
      if (Array.isArray(record.value)) {
        return record.value.join(',')
      }
      const allowed_values = getSecondAllowValue(
        record,
        'origin_field',
        record.origin_operator,
      )
      if (allowed_values?.length) {
        return getOptionsLabel(allowed_values, record.value)
      }
      return record.value
    },

    // render({ record }) {
    //   if (!Array.isArray(record.value))
    //     return
    //   if (record.value.length > 1)
    //     record.value.join(',')
    //   const allowed_values = getSecondAllowValue(
    //     record,
    //     'origin_field',
    //     record.origin_operator,
    //   )
    //   if (!allowed_values?.length)
    //     return record.value.join(',')
    //   return getOptionsLabel(allowed_values, record.value.toString())
    // },
  },
])
defineExpose({
  generateTemplate,
  reset,
  validate,
})

// function getValue(record: any) {
// }
</script>

<template>
  <section>
    <template v-if="!disabledAll">
      <div class="matching-rule-view min-w-[564px]">
        <div class="matching-rule-view__top">
          <section class="field flex gap-x-1">
            <div
              class="field w-[340px]"
              :class="{ '!w-[168px]': hasCustom }"
            >
              匹配字段
            </div>
            <div
              v-if="hasCustom"
              class="field w-[168px]"
            />
          </section>
          <div class="field w-[128px]">
            运算符
          </div>
          <div
            class="field min-w-[200px] flex-1"
            :class="{ 'opacity-0': !showValueColumn }"
          >
            值
          </div>
          <div class="field w-8 text-center">
            操作
          </div>
        </div>
        <div class="matching-rule-view__body">
          <matching-group
            v-for="(group, index) in matchingGroups"
            ref="groupRefs"
            :key="group.uuid"
            v-model:rules="group.rules"
            :last="index === matchingGroups.length - 1"
            :disabled-all="disabledAll"
            @delete="matchingGroups.splice(index, 1)"
            @change="handleGroupRuleChange(group.uuid, $event)"
          />
          <!--
        <div class="matching-rule-view__footer">
        <a-button
          v-if="!disabledAll"
          plain
          type="primary"
          class="w-[56px] h-[26px]"
          @click="handleAddGroup">
          <i-icons-btn-add-primary />
          <span>或者</span>
        </a-button>
      </div> -->
        </div>
      </div>
    </template>
    <template v-else>
      <a-table
        :columns="columns"
        :data="tableData"
        :pagination="false"
      />
    </template>
  </section>
</template>

<style lang="less">
@import './styles.less';
</style>
